/*********************************************************************************
 *Copyright(C),1996-2022,ChenJiehong
 *FileName:  lin_api.h
 *Author:  ChenJiehong
 *Version:  V1.0
 *Date: 2023-04-18
 **********************************************************************************/

#ifndef __LIN_API_H__
#define __LIN_API_H__

/***************************************Includes***********************************/
#include "nsuc16xx_conf.h"
#include "lin_type.h"
#include "lin_signals.h"

/***************************************Macros***********************************/

/* LIN Baudrate*/
#define LIN_BAUDRATE 19200

#if LIN_BAUDRATE == 19200
#define UART_BRR (1667 - 1)
#endif

/* Diagnostic frame data buffer array, excluding SID */
#define DIAG_DATA_BUFF_SIZE         (150U)


/***************************************Variables***********************************/
typedef enum
{
    LIN_MSG_TYPE_RX = 0U,  /*received data from sender for slave; */
    LIN_MSG_TYPE_TX,       /*data request from sender for slave; */
    LIN_MSG_TYPE_TX_EVENT, /*event trigger data request from sender for slave; */
} LinMessageType_t;

typedef enum
{
    LIN_CHECKSUM_CLASSIC = 0U, /*!< classic checksum does not include ID Byte.  */
    LIN_CHECKSUM_ENHANCED      /*!< "enhanced" checksum includes ID Byte.  */
} ChecksumType_t;

typedef enum
{
    LIN_STATE_IDLE,
    LIN_STATE_BREAK_SYNC,
    LIN_STATE_IDENTIFIER,
    LIN_STATE_RECEIVE_DATA,
    LIN_STATE_SEND_DATA
} l_Protocol_State_t;


typedef enum
{
    LIN_NET_STATE_INIT,
    LIN_NET_STATE_ACTIVE,
    LIN_NET_STATE_SLEEP,
} l_Network_State_t;


/** Status word type */
typedef union
{
    struct
    {
        l_bool ErrorInResponse : 1; /**< Error in response flag */
        l_bool SuccessfulTrans : 1; /**< Successful transfer flag */
        l_bool Overrun : 1;         /**< Few frames were processed since the previous call */
        l_bool GoToSleep : 1;       /**< Go to Sleep command was received */
        l_bool BusActivity : 1;     /**< Node has detected activity on the bus */
        l_bool EventTriggered : 1;  /**< Always 0 (zero) for Slave node */
        l_bool SaveConfig : 1;      /**< Save configuration request was received */
        l_u8 unused : 1;
        l_u8 PID : 8; /**< Protected ID */
    } mapped;

    l_u16 word; /**< Full ifc status word */
} l_s_IfcStatus_t;

typedef struct
{
    uint8_t frame_id;             /*!< frame ID.  */
    LinMessageType_t msg_type;    /*!< Type of message, rx,tx or event trigger.  */
    ChecksumType_t checksum_type; /*!< Type of checksum (enhanced or classic).  */
    uint8_t length;               /*!< Number of bytes in the data. */
    union
    {
        uint8_t data[8]; /*!< data buffer. */
        uint16_t data16[4];
        uint32_t data32[2];
    };
    uint8_t responseValid;
    uint8_t frameIsValid;
} LIN_Device_Frame_t;

typedef struct
{
    uint8_t length;
    ChecksumType_t checksum_type;

    uint8_t pid;
    uint8_t data[8];
    uint8_t checksum;

} l_Frame_t;

typedef enum
{
    l_erNOERR = 0,     /* This error should not be generated                                        */
    l_erIdParity,      /* Parity error in ID field received               	                        */
    l_erCheckSum,      /* Checksum error in message received              	                        */
    l_erBit,           /* Data collision during the transmit cycle        	                        */
    l_erDataFraming,   /* Stop or Start bit error while receiving data 	                            */
    l_erSynchField,    /* Sync field timing error                         	                        */
    l_erShort,         /* Short detected on the LIN bus                   	                        */
    l_erBreakDetected, /* A header has been detected inside a frame 		                        */
} l_LinError;

typedef union
{
    struct
    {
        uint8_t nad;

        union
        {
            uint8_t pci;
            struct
            {
                uint8_t pci_extInfo : 4;
                uint8_t pci_type : 4;
            };
        };

        union
        {
            struct
            {
                union
                {
                    uint8_t sid;
                    uint8_t rsid;
                };
                union
                {
                    struct
                    {
                        uint8_t D1;
                        uint8_t D2;
                        uint8_t D3;
                        uint8_t D4;
                        uint8_t D5;
                    };
                    uint8_t payload[5];
                };
            } SF;
            struct
            {
                uint8_t length;
                uint8_t sid;
                union
                {
                    struct
                    {
                        uint8_t D1;
                        uint8_t D2;
                        uint8_t D3;
                        uint8_t D4;
                    };
                    uint8_t payload[4];
                };
            } FF;
            struct
            {
                union
                {
                    struct
                    {
                        uint8_t D1;
                        uint8_t D2;
                        uint8_t D3;
                        uint8_t D4;
                        uint8_t D5;
                        uint8_t D6;
                    };
                    uint8_t payload[6];
                };
            } CF;
            uint8_t payload[6];
        };
    };
    uint8_t data[8];
} NodeStruct_t;

typedef enum
{
    LIN_PCI_SF = 0U,
    LIN_PCI_FF,
    LIN_PCI_CF
} PCI_Types_t;

typedef enum
{
    PDU_TYPE_SINGLE_PDU = 0U,
    PDU_TYPE_MULTI_PDU,
} PDU_Types_t;

typedef struct
{
    uint8_t nad;               
    uint8_t sid;              /*  sid */
    PDU_Types_t type;         /*  pdu type single or multi pdu */
    uint16_t packLength;      /*  the complete valid data buffer length except the length of sid   */
    uint16_t packCurrIndex;   /*  the current data position index in the complete data buffer     */
    uint16_t frameDataLength; /*  the current frame valid data length    */
    uint8_t *payload;         /*  data in received buffer */
    uint8_t frameCount;
    uint8_t errorCode;
} DiagReqInfo_t;

typedef struct
{
    uint8_t rsid; /*  rsid */
    uint8_t nad;
    PDU_Types_t type;    /*  pdu type single or multi pdu */
    uint16_t packLength; /*  the complete valid data buffer length except the length of SID   */
    uint8_t *payload;    /*  data buffer to be sent except SID*/
    uint16_t packCurrIndex;
    uint8_t frameCount;
} DiagRspInfo_t;

typedef enum
{
    l_reasonMaster = 0,
    l_reasonTimeOutDominant,
} l_SleepReason;

typedef struct
{
    uint16_t supplierID;
    uint16_t functionID;
    uint8_t newNAD;
} AssignNAD_t;

typedef struct
{
    uint8_t startIndex;
    uint8_t pid[4];
} AssignFrameIDRange_t;

typedef void (*ls_UnconditionalReqCallback_t)(LIN_Device_Frame_t const *frame);
typedef void (*ls_UnconditionalRspCallback_t)(LIN_Device_Frame_t *const frame);
typedef void (*ls_DiagReqCallback_t)(const DiagReqInfo_t *const diagReq, DiagRspInfo_t *const diagRsp);
typedef void (*ls_DiagFunctionalNADCallback_t)(const NodeStruct_t *const frame);
typedef void (*ls_SleepReqCallback_t)(l_SleepReason Reason);

typedef void (*ls_DiagReqLogCallback_t)(const LIN_Device_Frame_t *const frame);
typedef void (*ls_FrameIdLogCallback_t)(uint8_t frameId);

typedef struct
{
    ls_UnconditionalReqCallback_t unconditionalSubscribedCallback; /* received data from master */
    ls_UnconditionalRspCallback_t unconditionalPublishedCallback;  /* send data to master */
    ls_DiagReqCallback_t diagnosticSubscribedCallback;             /* Diagnostic and MultiPDU received data from master */
    ls_DiagFunctionalNADCallback_t diagFunctionalNADCallback;      /* special functional NAD (0x7E) handler*/
    ls_SleepReqCallback_t sleepRequestCallback;                    /* Diagnostic sleep request from master   */
} ls_LinsFramesCallback_t;

/***************************************Functions***********************************/
extern void lins_init(void);
extern void ls_ErrorDetected(l_LinError Error);
extern void l_N_AS_TimeoutStart(void);

l_bool l_sys_init(void);
l_bool l_ifc_init_sl1(void);

void ls_register_services(LIN_Device_Frame_t *frameTable, l_u8 tableSize, const ls_LinsFramesCallback_t *pFunCallback);

void l_handle_diagnostic_response(DiagRspInfo_t *rsp);

l_u16 l_ifc_read_status_sl1(void);
void l_ifc_save_congfige_sl1(void);

void l_DiagClearPendingResponse(void);
void l_DiagClearPendingConsecutiveFrame(void);
void l_BusSilentCheck(void);

#endif
/* [] END OF lin_api.h */
